package cn.congine.wizarpos.mall.action;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;

import cn.congine.wizarpos.mall.common.RespMessage;
import cn.congine.wizarpos.mall.entity.MrtMerchantCarousel;
import cn.congine.wizarpos.mall.model.ErpProduct;
import cn.congine.wizarpos.mall.model.WxAddress;
import cn.congine.wizarpos.mall.model.open.AccessTokenInput;
import cn.congine.wizarpos.mall.model.open.Address;
import cn.congine.wizarpos.mall.model.open.AddressDetailInput;
import cn.congine.wizarpos.mall.model.open.AddressDetailOutput;
import cn.congine.wizarpos.mall.model.open.AddressEditInput;
import cn.congine.wizarpos.mall.model.open.AddressEditOutput;
import cn.congine.wizarpos.mall.model.open.AddressGainInput;
import cn.congine.wizarpos.mall.model.open.AddressGainOutput;
import cn.congine.wizarpos.mall.model.open.CanyinSalesOrderSubmitInput;
import cn.congine.wizarpos.mall.model.open.CanyinSalesOrderSubmitOutput;
import cn.congine.wizarpos.mall.model.open.Category;
import cn.congine.wizarpos.mall.model.open.CateringDetail;
import cn.congine.wizarpos.mall.model.open.CateringMerchantDeliveryDefInput;
import cn.congine.wizarpos.mall.model.open.CateringMerchantDeliveryDefOutput;
import cn.congine.wizarpos.mall.model.open.CateringSaleOrderBindingInput;
import cn.congine.wizarpos.mall.model.open.CateringSaleOrderBindingOutput;
import cn.congine.wizarpos.mall.model.open.CateringSaleOrderMemberCardPayInput;
import cn.congine.wizarpos.mall.model.open.CateringSaleOrderMemberCardPayOutput;
import cn.congine.wizarpos.mall.model.open.CateringSaleOrderQueryInput;
import cn.congine.wizarpos.mall.model.open.CateringSaleOrderQueryOutput;
import cn.congine.wizarpos.mall.model.open.CommonResultOutput;
import cn.congine.wizarpos.mall.model.open.DefaultAddressInput;
import cn.congine.wizarpos.mall.model.open.DefaultAddressOutput;
import cn.congine.wizarpos.mall.model.open.GetShopInfoInput;
import cn.congine.wizarpos.mall.model.open.GetShopInfoOutput;
import cn.congine.wizarpos.mall.model.open.Merchandise;
import cn.congine.wizarpos.mall.model.open.MerchandiseSyncInput;
import cn.congine.wizarpos.mall.model.open.MerchandiseSyncOutput;
import cn.congine.wizarpos.mall.model.open.MerchantDef;
import cn.congine.wizarpos.mall.model.open.MerchantDefQueryInput;
import cn.congine.wizarpos.mall.model.open.MerchantDefQueryOutput;
import cn.congine.wizarpos.mall.model.open.OrderDetail;
import cn.congine.wizarpos.mall.model.open.ProductCategorySyncInput;
import cn.congine.wizarpos.mall.model.open.ProductCategorySyncOutput;
import cn.congine.wizarpos.mall.model.open.SaleOrder;
import cn.congine.wizarpos.mall.model.open.ShopInfoPair;
import cn.congine.wizarpos.mall.model.open.TicketInfoPayUse;
import cn.congine.wizarpos.mall.model.open.WeChartMemberInfoQueryInput;
import cn.congine.wizarpos.mall.model.open.WeChartMemberInfoQueryOutput;
import cn.congine.wizarpos.mall.service.MrtMerchantCarouselService;
import cn.congine.wizarpos.mall.service.impl.WPosHttpClient;
import cn.congine.wizarpos.mall.service.impl.WizarposOpenRestClient;
import cn.congine.wizarpos.mall.utils.Function;
import cn.congine.wizarpos.mall.utils.SysConstants;
import cn.congine.wizarpos.mall.utils.Utils;
import cn.congine.wizarpos.mall.utils.WxSignUtil;
import cn.congine.wizarpos.mall.vo.ProductView;

/**
 * 外卖用（新版）
 * 
 * @author xudongdong
 *         2016年1月5日 下午1:45:49
 */
@Controller
@RequestMapping(value = "/waimai")
public class WaimaiAction {
	private Logger logger = Logger.getLogger(WaimaiAction.class);

	@Autowired
	private WPosHttpClient wPosHttpClient;
	@Autowired
	private WizarposOpenRestClient wizarposOpenRestClient;
	 
	@Resource(name = "messageSource")
	private MessageSource messageSource;
	
	@Autowired
	private MrtMerchantCarouselService mrtMerchantCarouselService;
	/**
	 * 点单详情
	 * 
	 * @param mid
	 * @param orderId
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	@RequestMapping(value = "/order_detail")
	public ModelAndView orderDetail(
			@RequestParam(value = "orderId", required = true) String orderId,
			@RequestParam(value = "mid", required = true) String mid,
			HttpServletRequest httpRequest) {
		String openId = (String) httpRequest.getSession().getAttribute("openId");
		String cardId = (String) httpRequest.getSession().getAttribute("mrtCardId");
		if (StringUtils.isEmpty(openId) || StringUtils.isEmpty(cardId)) {//session过期，跳转到登录注册页面
			return new ModelAndView("forward:/vip/login");
		}
		int productsNum = 0;
		
		CateringSaleOrderQueryInput input = new CateringSaleOrderQueryInput();
		input.setMid(mid);
		input.setOrderId(orderId);
		CateringSaleOrderQueryOutput output = (CateringSaleOrderQueryOutput) wizarposOpenRestClient.post(input, "/catering/saleorder/query", CateringSaleOrderQueryOutput.class);		

		if (output == null || !SysConstants.OPEN_SUCCESS.equals(output.getCode())) {
			logger.error("餐饮订单查询失败，单号：" + orderId);
			if (output != null) {
				logger.error("餐饮订单查询失败：" + output.getMessage());
				if (SysConstants.NO_MERCHANT_CODE.equals(output.getCode())) {
					return new ModelAndView("error").addObject("err_message",
							SysConstants.NO_MERCHANT);
				}
			} else {
				return new ModelAndView("error").addObject("err_message",
						SysConstants.OPEN_ERROR_MESSAGE);
			}
		}
		
		SaleOrder result = output.getResult();
		if (result == null) {
			 return new ModelAndView("error").addObject("err_message",
						SysConstants.OPEN_ERROR_MESSAGE);
		}
		List<OrderDetail> orderDetails = output.getResult().getOrderDetail();
		if (orderDetails != null) {
			for (OrderDetail od : orderDetails) {
				productsNum += Integer.valueOf(od.getQty());
			}
		}
		result.setOrderNo(Function.getShowSaleOrderNo(result.getOrderNo()));
		
//		result.setStatus("未下单");
		
		switch (result.getStatus()) {
			case "-1": 
				result.setStatus("未下单"); 
				break;
			case "0": 
				result.setStatus("未支付"); 
				break;
			case "1": 
				result.setStatus("已完成"); 
				break;
			case "2": 
				result.setStatus("已取消"); 
				break;
		}
		
		//1堂吃2快餐3外卖
 		switch (result.getOrderType()) {
			case "1": 
				result.setOrderType("堂食"); 
				break;
			case "2": 
				result.setOrderType("快餐"); 
				break;
			case "3": 
				result.setOrderType("外卖"); 
				break;
		}
		
		//请求微信 js api的完整页面地址
		String baseUrl = "http://"
				+ messageSource.getMessage(SysConstants.SERVICE_DNS , null,
						Locale.ENGLISH);
		baseUrl += httpRequest.getSession().getServletContext().getContextPath();
		StringBuffer tmpUrl = new StringBuffer();
		tmpUrl.append(baseUrl);
		tmpUrl.append("/dgd/order_detail");
		tmpUrl.append("?mid="+mid);
		tmpUrl.append("&orderId="+orderId);
		String url = tmpUrl.toString();		
		// 请求微信api的ticket
		AccessTokenInput jsInput = new AccessTokenInput();
		jsInput.setMid(mid);
		
		CommonResultOutput jsOutput = (CommonResultOutput) wizarposOpenRestClient.post(jsInput, "/weixin/ticket/js", CommonResultOutput.class);		
		if (jsOutput == null || SysConstants.OPEN_ERROR.equals(jsOutput.getCode())) {
			return new ModelAndView("error").addObject("err_message",
					SysConstants.OPEN_ERROR);
		} else if (SysConstants.NO_MERCHANT_CODE.equals(jsOutput.getCode())) {
			return new ModelAndView("error").addObject("err_message",
					SysConstants.NO_MERCHANT);
		} 
		
		Map<String, String> jsresult = (Map<String, String>) jsOutput.getResult();
		String jsTicket = jsresult.get("ticket");
		String appId = jsresult.get("appid");
		//微信 js config 签名
		Map<String, String> ret = WxSignUtil.commonSign(jsTicket, url,
				WxSignUtil.createTimestamp());
				
				
		return new ModelAndView("dgd_order/order_detail")
			.addObject("mid", mid)
			.addObject("orderId", orderId)
			.addObject("productsNum", productsNum)
			.addObject("order", result)
			.addObject("appId", appId)
			.addAllObjects(ret);
	}

	/**
	 * 跳转到提交订单页
	 * 
	 * @param sum
	 * @param mid
	 * @param orderDetail
	 * @param httpRequest
	 * @return
	 * @throws IOException
	 */
	@RequestMapping(value = "/order_confirm")
	public ModelAndView orderConfirm(
			@RequestParam(value = "sum", required = true) String sum,
			@RequestParam(value = "mid", required = true) String mid,
			@RequestParam(value = "shopMid", required = false) String shopMid,
			@RequestParam(value = "orderDetail", required = true) String orderDetail,
			HttpServletRequest httpRequest) throws IOException
	{
		String cardId = (String) httpRequest.getSession().getAttribute("mrtCardId");
		if (StringUtils.isEmpty(cardId)) {//session过期，跳转到登录注册页面
			return new ModelAndView("forward:login");
		}
		String token = (String) httpRequest.getSession().getAttribute("token");
		Map<String, Object> data = new HashMap<String, Object>();
		if (StringUtils.isEmpty(shopMid)) {
			shopMid = mid;
		}
		// 餐饮外卖配送定义查询接口
		CateringMerchantDeliveryDefInput deliveryDefInput = new CateringMerchantDeliveryDefInput();
		deliveryDefInput.setMid(shopMid);
		CateringMerchantDeliveryDefOutput deliveryDefOutput = (CateringMerchantDeliveryDefOutput) wizarposOpenRestClient
				.post(deliveryDefInput, "/catering/delivery/def",
						CateringMerchantDeliveryDefOutput.class);
		if (deliveryDefOutput == null) {
			logger.error("请求开放平台餐饮外卖配送定义查询接口失败");
			logger.error("mid："+shopMid);
			return new ModelAndView("error").addObject("err_message",
					SysConstants.OPEN_ERROR_MESSAGE);			
		} else if (SysConstants.OPEN_SUCCESS.equals(deliveryDefOutput.getCode())) {
			CateringMerchantDeliveryDefOutput.Result result = deliveryDefOutput.getResult();
			List<String> times = new ArrayList<String>();
			times.add("尽快送出");
			Date now = new Date();
			if (!StringUtils.isEmpty(result.getShopHours())) {
				String[] shopHours =  result.getShopHours().split("-");
				// 设置送餐时间
				SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
				try {
					Date startTime = sdf.parse(shopHours[0]);
					Date time = null;
					Date nowTime = sdf.parse(sdf.format(now));
					if (startTime.compareTo(nowTime) <= 0) {
						time = Function.addMinute(nowTime, 30);
					} else {
						time = Function.addMinute(startTime, 30);
					}
					Date endTime = sdf.parse(shopHours[1]);
					while (time.compareTo(endTime) <= 0) {
						times.add(sdf.format(time));
						time = Function.addMinute(time, 30);
					}
					data.put("times", times);					
					
				} catch (ParseException e) {
					logger.error("解析营业时间出错");
					logger.error("mid：" + mid);
					logger.error("shopHours：" + shopHours);	
					return new ModelAndView("error").addObject("err_message",
							shopHours);
				}
				
			} else {
				// 设置送餐时间
				SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
				Date dayEnd = Function.getDayEnd();
				Date time = Function.addMinute(now, 30);
				while (time.compareTo(dayEnd) <= 0) {
					times.add(sdf.format(time));
					time = Function.addMinute(time, 30);
				}
				data.put("times", times);				
			}
			if ("1".equals(result.getCashOnDelivery())) {
				data.put("cashOnDelivery", "1");
			} else {
				data.put("cashOnDelivery", "0");
			}
			if ("1".equals(result.getCashOnMember())) {
				data.put("cashOnMember", "1");
			} else {
				data.put("cashOnMember", "0");
			}
		} else {
			logger.error("code："+deliveryDefOutput.getCode());
			logger.error("message："+deliveryDefOutput.getMessage());
			return new ModelAndView("error").addObject("err_message",
					deliveryDefOutput.getMessage());
		}

		data.put("sum", sum);
		data.put("mid", mid);
		data.put("cardId", cardId);
		data.put("orderDetail", orderDetail);
		List<TicketInfoPayUse> tickets = wPosHttpClient.getPayUseTickets(mid, cardId);
		if (tickets != null) {
			data.put("ticketNum", tickets.size());
		} else {
			data.put("ticketNum", 0);
		}
		data.put("cashList", tickets);

		DefaultAddressInput in = new DefaultAddressInput();
		in.setMid(mid);
		in.setCardId(cardId);
		DefaultAddressOutput out = (DefaultAddressOutput) wizarposOpenRestClient.post(in, "/address/default", DefaultAddressOutput.class);								
		if (out == null) {
			logger.error("请求开放平默认地址接口失败");
			logger.error("mid："+mid);
			logger.error("cardId："+cardId);
			return new ModelAndView("error").addObject("err_message",
					SysConstants.OPEN_ERROR_MESSAGE);			
		} else if (SysConstants.OPEN_SUCCESS.equals(out.getCode())) {
			WxAddress address = (WxAddress) out.getWxAddress();
			if (address != null) {
				data.put("address", address);
				data.put("hasAddress", 1);
			} else {
				data.put("hasAddress", 0);
			}
		} else {
			logger.error("code：" + out.getCode());
			logger.error("message：" + out.getMessage());
			return new ModelAndView("error").addObject("err_message",
					out.getMessage());			
		}
		data.put("token", token);
		return new  ModelAndView("waimai/waimai_submit", data);
	}

	/**
	 * 从选择地址页返回提交订单页
	 * 
	 * @param sum
	 * @param mid
	 * @param orderDetail
	 * @param httpRequest
	 * @return
	 * @throws IOException
	 */
	@RequestMapping(value = "/return_order")
	public ModelAndView returnOrder(
			@RequestParam(value = "sum", required = true) String sum,
			@RequestParam(value = "mid", required = true) String mid,
			@RequestParam(value = "shopMid", required = false) String shopMid,
			@RequestParam(value = "addressId", required = true) String addressId,
			HttpServletRequest httpRequest) throws IOException
	{
		String cardId = (String) httpRequest.getSession().getAttribute("mrtCardId");
		if (StringUtils.isEmpty(cardId)) {//session过期，跳转到登录注册页面
			return new ModelAndView("forward:login");
		}
		String token = (String) httpRequest.getSession().getAttribute("token");
		Map<String, Object> data = new HashMap<String, Object>();
		
		WxAddress address = null;
		AddressDetailInput in = new AddressDetailInput();
		in.setMid(mid);
		in.setId(addressId);
		AddressDetailOutput out = (AddressDetailOutput) wizarposOpenRestClient.post(in, "/address/detail", AddressDetailOutput.class);								
		if (out == null) {
			logger.error("请求开放平台地址详情接口失败");
			logger.error("mid："+mid);
			logger.error("addressId："+addressId);
			return new ModelAndView("error").addObject("err_message",
					SysConstants.OPEN_ERROR_MESSAGE);			
		} else if (SysConstants.OPEN_SUCCESS.equals(out.getCode())) {
			address = (WxAddress) out.getResult();
		} else {
			logger.error("code：" + out.getCode());
			logger.error("message：" + out.getMessage());
			return new ModelAndView("error").addObject("err_message",
					out.getMessage());			
		}
		data.put("address", address);
		if (StringUtils.isEmpty(shopMid)) {
			shopMid = mid;
		}
		// 餐饮外卖配送定义查询接口
		CateringMerchantDeliveryDefInput deliveryDefInput = new CateringMerchantDeliveryDefInput();
		deliveryDefInput.setMid(shopMid);
		CateringMerchantDeliveryDefOutput deliveryDefOutput = (CateringMerchantDeliveryDefOutput) wizarposOpenRestClient
				.post(deliveryDefInput, "/catering/delivery/def",
						CateringMerchantDeliveryDefOutput.class);
		if (deliveryDefOutput == null) {
			logger.error("请求开放平台餐饮外卖配送定义查询接口失败");
			logger.error("mid："+shopMid);
			return new ModelAndView("error").addObject("err_message",
					SysConstants.OPEN_ERROR_MESSAGE);			
		} else if (SysConstants.OPEN_SUCCESS.equals(deliveryDefOutput.getCode())) {
			CateringMerchantDeliveryDefOutput.Result result = deliveryDefOutput.getResult();
			List<String> times = new ArrayList<String>();
			times.add("尽快送出");
			Date now = new Date();
			if (!StringUtils.isEmpty(result.getShopHours())) {
				String[] shopHours =  result.getShopHours().split("-");
				// 设置送餐时间
				SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
				try {
					Date startTime = sdf.parse(shopHours[0]);
					Date time = null;
					Date nowTime = sdf.parse(sdf.format(now));
					if (startTime.compareTo(nowTime) <= 0) {
						time = Function.addMinute(nowTime, 30);
					} else {
						time = Function.addMinute(startTime, 30);
					}
					Date endTime = sdf.parse(shopHours[1]);
					while (time.compareTo(endTime) <= 0) {
						times.add(sdf.format(time));
						time = Function.addMinute(time, 30);
					}
					data.put("times", times);					
					
				} catch (ParseException e) {
					logger.error("解析营业时间出错");
					logger.error("mid：" + mid);
					logger.error("shopHours：" + shopHours);	
					return new ModelAndView("error").addObject("err_message",
							shopHours);
				}
				
			} else {
				// 设置送餐时间
				SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
				Date dayEnd = Function.getDayEnd();
				Date time = Function.addMinute(now, 30);
				while (time.compareTo(dayEnd) <= 0) {
					times.add(sdf.format(time));
					time = Function.addMinute(time, 30);
				}
				data.put("times", times);				
			}
			if ("1".equals(result.getCashOnDelivery())) {
				data.put("cashOnDelivery", "1");
			} else {
				data.put("cashOnDelivery", "0");
			}
			if ("1".equals(result.getCashOnMember())) {
				data.put("cashOnMember", "1");
			} else {
				data.put("cashOnMember", "0");
			}
		} else {
			logger.error("code："+deliveryDefOutput.getCode());
			logger.error("message："+deliveryDefOutput.getMessage());
			return new ModelAndView("error").addObject("err_message",
					deliveryDefOutput.getMessage());
		}
		data.put("hasAddress", 1);
		data.put("sum", sum);
		data.put("mid", mid);
		data.put("cardId", cardId);
		List<TicketInfoPayUse> tickets = wPosHttpClient.getPayUseTickets(mid, cardId);
		if (tickets != null) {
			data.put("ticketNum", tickets.size());
		} else {
			data.put("ticketNum", 0);
		}
		data.put("cashList", tickets);
		data.put("token", token);
		data.put("shopMid", shopMid);
		return new  ModelAndView("waimai/waimai_submit", data);
	}
	
	/**
	 * 取消订单
	 * 
	 * @param mid
	 * @param openId
	 * @param orderId
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	@RequestMapping(value = "/order_cancel")
	public @ResponseBody RespMessage orderCancel(
			@RequestParam(value = "orderId", required = true) String orderId,
			@RequestParam(value = "mid", required = true) String mid,
			HttpServletRequest httpRequest) {
		RespMessage res = new RespMessage();	
		
		String openId = (String) httpRequest.getSession().getAttribute("openId");
		String cardId = (String) httpRequest.getSession().getAttribute("mrtCardId");
		if (StringUtils.isEmpty(openId) || StringUtils.isEmpty(cardId)) {//session过期，跳转到登录注册页面
			res.setCode(2);
			return res;	
		}
		JSONObject resJson = wPosHttpClient.waimaiCancel(mid, orderId);
		if (resJson != null && "0".equals(resJson.getString("code"))) {
			return res;
		} else {
			res.setCode(-1);
			res.setMessage("订单取消失败");
			if (resJson == null) {
				logger.error("请求member-server外卖退单1049接口失败");
			} else {
				logger.error(resJson.toString());
			}
			return res;
		}
		
	}
	
	/**
	 * 外卖菜单页
	 * 
	 * @param mid
	 * @param httpRequest
	 * @return
	 */
	@RequestMapping(value = "/tomenu", method = RequestMethod.GET)
	@ResponseBody
	public ModelAndView toMenu(
			@RequestParam(value = "mid", required = true) String mid,
			@RequestParam(value = "startMenu", required = false) String startMenu,
			@RequestParam(value = "shopMid", required = false) String shopMid,
			HttpServletRequest httpRequest) {
		String openId = (String) httpRequest.getSession().getAttribute("openId");
		String cardId = (String) httpRequest.getSession().getAttribute("mrtCardId");
		if (StringUtils.isEmpty(openId) || StringUtils.isEmpty(cardId)) { //session过期，跳转到登录注册页面
			return new ModelAndView("forward:/vip/login");
		}	
		Map<String, Object> data = new HashMap<String, Object>();
		String isMainStore = "0";
		// 请求开放平台获取商户信息
		MerchantDefQueryInput merchantDefQueryInput = new MerchantDefQueryInput();
		merchantDefQueryInput.setMid(mid);
		MerchantDefQueryOutput merchantDefQueryOutput = (MerchantDefQueryOutput) wizarposOpenRestClient.post(merchantDefQueryInput,"/merchantdef/info",MerchantDefQueryOutput.class);
		if (merchantDefQueryOutput != null && SysConstants.OPEN_SUCCESS.equals(merchantDefQueryOutput.getCode())) {
			MerchantDef merchantDef = merchantDefQueryOutput.getResult();
			isMainStore = merchantDef.getIsVirtualMainStore();
			data.put("merchantName", merchantDef.getMerchantName());
			data.put("isMainStore", isMainStore);
			data.put("bannerImage", merchantDef.getBannerImage());
		} else {
			logger.error("请求开放平台获取商户信息失败");
			if (merchantDefQueryOutput == null) {
				logger.error("系统错误");
			} else {
				logger.error("code：" + merchantDefQueryOutput.getCode());
				logger.error("message：" + merchantDefQueryOutput.getMessage());
			}
			return new ModelAndView("error").addObject("err_message", SysConstants.OPEN_ERROR_MESSAGE);
			
		}
		// url地址
		String baseUrl = getBaseURL(httpRequest);
		StringBuffer tmpUrl = new StringBuffer();
		tmpUrl.append(baseUrl);
		tmpUrl.append("/waimai/tomenu");
		tmpUrl.append("?mid=");
		tmpUrl.append(mid);
		if (!StringUtils.isEmpty(startMenu)) {
			tmpUrl.append("&startMenu=");
			tmpUrl.append(startMenu);	
		}
		if (!StringUtils.isEmpty(shopMid)) {
			tmpUrl.append("&shopMid=");
			tmpUrl.append(shopMid);	
		}
		String url = tmpUrl.toString();
		Map<String, String> jsApiConfig = wPosHttpClient.weixinJsApiTicketConfig(mid, url);
		if (jsApiConfig != null) {
			data.putAll(jsApiConfig);
		} else {
			logger.error("来份外卖获取地址签名失败");
			return new ModelAndView("error").addObject("err_message",
					SysConstants.OPEN_ERROR);
		}
		
		// 总分店模式：选择门店
		if (!"1".equals(startMenu) && "1".equals(isMainStore)) {
			// 获取商家信息
			GetShopInfoInput getShopInfoInput = new GetShopInfoInput();
			getShopInfoInput.setMid(mid);
			getShopInfoInput.setType("2"); // 2外卖、堂食
			GetShopInfoOutput getShopInfoOutput = (GetShopInfoOutput) wizarposOpenRestClient.post(getShopInfoInput, "/dzx/getShopInfo", GetShopInfoOutput.class);								
			if (getShopInfoOutput == null) {
				logger.error("请求开放平台获取商户信息（fid下mid集合）或门店信息（mid下sn集合）接口失败");
				logger.error("mid："+mid);
				return new ModelAndView("error").addObject("err_message", SysConstants.OPEN_ERROR_MESSAGE);			
			} else if (!SysConstants.OPEN_SUCCESS.equals(getShopInfoOutput.getCode())) {
				logger.error("code：" + getShopInfoOutput.getCode());
				logger.error("message：" + getShopInfoOutput.getMessage());
				return new ModelAndView("error").addObject("err_message", getShopInfoOutput.getMessage());	
			}
			List<ShopInfoPair> shopInfoPairs = getShopInfoOutput.getResult().getShopInfoPairs();
			if (shopInfoPairs.size() < 2) { // 总店下无分店或仅有一家分店
				data.put("shopMid", shopInfoPairs.get(0).getMid());
			} else {
				data.put("shopInfoPairs", JSON.toJSONString(shopInfoPairs, SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNonStringKeyAsString));
				data.put("mid", mid);
				data.put("isWaimai", "1");
				return new ModelAndView("waimai/start_menu", data);
			}
		}
		
		if (StringUtils.isEmpty(shopMid)) {
			shopMid = mid;
		}
		ProductCategorySyncInput productCategorySyncInput = new ProductCategorySyncInput();
		productCategorySyncInput.setMid(shopMid);
		ProductCategorySyncOutput productCategorySyncOutput = (ProductCategorySyncOutput) wizarposOpenRestClient
				.post(productCategorySyncInput, "/product/category",
						ProductCategorySyncOutput.class);
		
		if (productCategorySyncOutput == null || !SysConstants.OPEN_SUCCESS.equals(productCategorySyncOutput.getCode())) {
			logger.error("餐饮品类查询失败，商户号：" + mid);
			if (productCategorySyncOutput != null) {
				logger.error("餐饮品类查询失败：" + productCategorySyncOutput.getMessage());
				if (SysConstants.NO_MERCHANT_CODE.equals(productCategorySyncOutput.getCode())) {
					return new ModelAndView("error").addObject("err_message",
							SysConstants.NO_MERCHANT);
				} else {
					return new ModelAndView("error").addObject("err_message",
							productCategorySyncOutput.getMessage());
				}
			} else {
				return new ModelAndView("error").addObject("err_message",
						SysConstants.OPEN_ERROR_MESSAGE);
			}
		}
		
		List<Category> categoryList = productCategorySyncOutput
				.getResult();

		Map<String, Object> products = new HashMap<String, Object>();
		// 查询第一个品类的商品
		boolean next = true;
		for (Category category : categoryList)
		{
			String isVirtual = category.getFlag();
			String categoryId = category.getId();
			String categoryCode = category.getCode();
			List<ErpProduct> productList = new ArrayList<ErpProduct>();
			if (next) {
				MerchandiseSyncInput merchandiseSyncInput = new MerchandiseSyncInput();
				merchandiseSyncInput.setMid(shopMid);
				merchandiseSyncInput.setCategoryId(categoryId);
				
				MerchandiseSyncOutput merchandiseSyncOutput = null;
				if ("1".equals(isVirtual)) {
					merchandiseSyncOutput = (MerchandiseSyncOutput) wizarposOpenRestClient
							.post(merchandiseSyncInput, "/product/virtual",
									MerchandiseSyncOutput.class);
				} else {
					merchandiseSyncOutput = (MerchandiseSyncOutput) wizarposOpenRestClient
						.post(merchandiseSyncInput, "/product/merchandise",
								MerchandiseSyncOutput.class);
				}
	
				if (merchandiseSyncOutput == null || !SysConstants.OPEN_SUCCESS.equals(merchandiseSyncOutput.getCode())) {
					logger.error("餐饮商品查询失败，商户号：" + shopMid + ",品类ID：" + categoryId);
					if (merchandiseSyncOutput != null) {
						logger.error("餐饮商品查询失败：" + merchandiseSyncOutput.getMessage());
						if (SysConstants.NO_MERCHANT_CODE.equals(merchandiseSyncOutput.getCode())) {
							return new ModelAndView("error").addObject("err_message",
									SysConstants.NO_MERCHANT);
						} else {
							return new ModelAndView("error").addObject("err_message",
									merchandiseSyncOutput.getMessage());
						}
					} else {
						return new ModelAndView("error").addObject("err_message",
								SysConstants.OPEN_ERROR_MESSAGE);
					}
				}
				
				List<Merchandise> productListTemp = merchandiseSyncOutput
						.getResult();
				// 处理价格分-元，图片路径
				for (Merchandise prt : productListTemp)
				{
					ErpProduct ep = new ErpProduct();
					ep.setId(prt.getProductId());
					ep.setCode(prt.getCode());
					ep.setName(prt.getName());
					ep.setPrice(prt.getPrice());
					ep.setShowMemPrice(prt.getMemberPrice());
					// 商品图片处理
					// 若无图片则设置默认图片（dgd_order/menu 页面内引用工程默认图片  images/default.jpg）
					if (!StringUtils.isEmpty(prt.getPicUrl())) {
						ep.setPicUrl(Function.dealGridPicUrl(prt.getPicUrl().split(",")[0], 150, 150));
					}
					ep.setProductAtts(prt.getProductAtts());
					ep.setUnit(prt.getUnit());
					productList.add(ep);
				}
				next = false;
			}
			products.put("topten" + categoryCode, productList);
		}

		data.put("dns", messageSource.getMessage(SysConstants.SERVICE_DNS, null,
				Locale.ENGLISH));

		
		// 餐饮外卖配送定义查询接口
		CateringMerchantDeliveryDefInput deliveryDefInput = new CateringMerchantDeliveryDefInput();
		deliveryDefInput.setMid(shopMid);
		CateringMerchantDeliveryDefOutput deliveryDefOutput = (CateringMerchantDeliveryDefOutput) wizarposOpenRestClient
				.post(deliveryDefInput, "/catering/delivery/def",
						CateringMerchantDeliveryDefOutput.class);
		if (deliveryDefOutput == null) {
			logger.error("请求开放平台餐饮外卖配送定义查询接口失败");
			logger.error("mid："+mid);
			return new ModelAndView("error").addObject("err_message",
					SysConstants.OPEN_ERROR_MESSAGE);			
		} else if (SysConstants.OPEN_SUCCESS.equals(deliveryDefOutput.getCode())) {
			CateringMerchantDeliveryDefOutput.Result result = deliveryDefOutput.getResult();
			
			if ("1".equals(result.getDeliveryStart())) { // 外卖起送费用(0不使用 1使用)
				data.put("deliveryStartFare", result.getDeliveryStartFare());
				data.put("deliveryStart", "1");
			} else {
				data.put("deliveryStartFare", "0.00");
				data.put("deliveryStart", "0");
			}
			if ("1".equals(result.getDeliveryFixed())) { // 固定运费(0不使用 1使用)
				data.put("deliveryFixedFare", result.getDeliveryFixedFare());
				data.put("deliveryFixed", "1");
			} else {
				data.put("deliveryFixedFare", "0.00");
				data.put("deliveryFixed", "0");
			}
			if ("1".equals(result.getBoxBaled())) { // 餐盒打包费(0不使用 1使用)
				data.put("boxBalePerFare", result.getBoxBalePerFare());
				data.put("boxBaled", "1");
			} else {
				data.put("boxBalePerFare", "0.00");
				data.put("boxBaled", "0");
			}
		} else {
			logger.error("code："+deliveryDefOutput.getCode());
			logger.error("message："+deliveryDefOutput.getMessage());
			return new ModelAndView("error").addObject("err_message",
					deliveryDefOutput.getMessage());
		}
		
		
		List<MrtMerchantCarousel> carousels = mrtMerchantCarouselService.getMrtMerchantCarouselList(mid);
		String carouselBaseUrl = getCaruselBaseURL(httpRequest);
		if (carousels != null && carousels.size() > 0) {
			if (carousels.size() == 1) {
				 data.put("bannerPath1", carouselBaseUrl + carousels.get(0).getFilePaths());
				 data.put("bannerUrl1", carousels.get(0).getFileUrl());
			} else if (carousels.size() == 2) {
				 data.put("bannerPath1", carouselBaseUrl + carousels.get(0).getFilePaths());
				 data.put("bannerPath2", carouselBaseUrl + carousels.get(1).getFilePaths());
				 data.put("bannerUrl1", carousels.get(0).getFileUrl());
				 data.put("bannerUrl2", carousels.get(1).getFileUrl());
			} else if (carousels.size() > 2) {
				 data.put("bannerPath1", carouselBaseUrl + carousels.get(0).getFilePaths());
				 data.put("bannerPath2", carouselBaseUrl + carousels.get(1).getFilePaths());
				 data.put("bannerPath3", carouselBaseUrl + carousels.get(2).getFilePaths());
				 data.put("bannerUrl1", carousels.get(0).getFileUrl());
				 data.put("bannerUrl2", carousels.get(1).getFileUrl());
				 data.put("bannerUrl3", carousels.get(2).getFileUrl());
			}
		}
//		data.put("bannerPath1", "/wizarpos-mall-sole/images/124734906751414439.jpg");
//		data.put("bannerUrl1", "/wizarpos-mall-sole/images/124734906751414439.jpg");
		 
		data.put("mid", mid);
		data.put("products", products);
		data.put("categoryList", categoryList);
		data.put("cardId", cardId);
		data.put("shopMid", shopMid);
		Utils.setSessionToken(httpRequest);
		return new ModelAndView("waimai/menu", data);
	}
	
	private String getBaseURL(HttpServletRequest httpRequest)
	{
		String baseUrl = "http://"
				+ messageSource.getMessage(SysConstants.SERVICE_DNS, null,
						Locale.ENGLISH);
		baseUrl += httpRequest.getSession().getServletContext()
				.getContextPath();
		return baseUrl;
	}
	
	private String getCaruselBaseURL(HttpServletRequest httpRequest)
	{
		String baseUrl = messageSource.getMessage(SysConstants.CAROUSEL_PATH, null,
								Locale.ENGLISH);
		return baseUrl;
	}

	/**
	 * 确认订单
	 * 
	 * @param sum
	 * @param mid
	 * @param orderDetail
	 * @param httpRequest
	 * @return
	 * @throws IOException
	 */
	@RequestMapping(value = "/save_order")
	public ModelAndView saveOrder(
			@RequestParam(value = "sum", required = true) String sum,
			@RequestParam(value = "mid", required = true) String mid,
			@RequestParam(value = "shopMid", required = true) String shopMid,
			@RequestParam(value = "orderDetail", required = true) String orderDetail,
			HttpServletRequest httpRequest) throws IOException
	{
		String openId = (String) httpRequest.getSession()
				.getAttribute("openId");
		if (StringUtils.isEmpty(openId))
		{// session过期，跳转到登录注册页面
			return new ModelAndView("forward:/vip/login");
		}
		Map<String, Object> data = new HashMap<String, Object>();
		if (StringUtils.isEmpty(shopMid)) {
			shopMid = mid;
		}
		
		// 餐饮外卖配送定义查询接口
		CateringMerchantDeliveryDefInput deliveryDefInput = new CateringMerchantDeliveryDefInput();
		deliveryDefInput.setMid(shopMid);
		CateringMerchantDeliveryDefOutput deliveryDefOutput = (CateringMerchantDeliveryDefOutput) wizarposOpenRestClient
				.post(deliveryDefInput, "/catering/delivery/def",
						CateringMerchantDeliveryDefOutput.class);
		float deliveryFixedFare = 0;
		float boxBalePerFare = 0;
		float boxBaleFare = 0;
		float totalSum = 0;
		if (deliveryDefOutput == null) {
			logger.error("请求开放平台餐饮外卖配送定义查询接口失败");
			logger.error("mid："+mid);
			return new ModelAndView("error").addObject("err_message",
					SysConstants.OPEN_ERROR_MESSAGE);			
		} else if (SysConstants.OPEN_SUCCESS.equals(deliveryDefOutput.getCode())) {
			CateringMerchantDeliveryDefOutput.Result result = deliveryDefOutput.getResult();
			if ("1".equals(result.getDeliveryFixed())) { // 固定运费(0不使用 1使用)
				data.put("deliveryFixedFare", result.getDeliveryFixedFare());
				data.put("deliveryFixed", "1");
				deliveryFixedFare = Float.parseFloat(result.getDeliveryFixedFare());
			} else {
				data.put("deliveryFixedFare", "0.00");
				data.put("deliveryFixed", "0");
			}
			if ("1".equals(result.getDeliveryStart())) { // 外卖起送费用(0不使用 1使用)
				data.put("deliveryStartFare", result.getDeliveryStartFare());
				data.put("deliveryStart", "1");
			} else {
				data.put("deliveryStartFare", "0.00");
				data.put("deliveryStart", "0");
			}
			if ("1".equals(result.getBoxBaled())) { // 餐盒打包费(0不使用 1使用)
				data.put("boxBalePerFare", result.getBoxBalePerFare());
				data.put("boxBaled", "1");
				boxBalePerFare = Float.parseFloat(result.getBoxBalePerFare());
			} else {
				data.put("boxBalePerFare", "0.00");
				data.put("boxBaled", "0");
			}
		} else {
			logger.error("code："+deliveryDefOutput.getCode());
			logger.error("message："+deliveryDefOutput.getMessage());
			return new ModelAndView("error").addObject("err_message",
					deliveryDefOutput.getMessage());
		}		
		
		JSONArray detailArray = JSON.parseArray(orderDetail);
		List<ProductView> list = new ArrayList<ProductView>();
		// 点餐数量
		int productsNum = 0;
		for (int i = 0; i < detailArray.size(); i++) {
			JSONObject detail = detailArray.getJSONObject(i);
			ProductView pv = new ProductView();
			pv.setI(String.valueOf(i));
			pv.setId(detail.getString("id"));
			pv.setName(URLDecoder.decode(detail.getString("name"), "UTF-8"));
			pv.setPrice(detail.getString("price"));
			pv.setNum(detail.getInteger("qty"));
			pv.setCode(detail.getString("code"));
			pv.setDesc(detail.getString("productRemark"));
			pv.setProductAttr(detail.getString("productAttr"));
			com.alibaba.fastjson.JSONArray proAttrs =  detail.getJSONArray("productAttrs");
			List<Map<String, Object>> productAttrs = null; 
			if (proAttrs != null) {
				productAttrs = new ArrayList<Map<String,Object>>();
				for (int j = 0; j < proAttrs.size(); j++) {
					productAttrs.add(proAttrs.getJSONObject(j));
				}
				pv.setProductAttrs(productAttrs);
			}
			productsNum += detail.getIntValue("qty");
			list.add(pv);
			totalSum += Float.parseFloat(detail.getString("price")) * detail.getInteger("qty");
		}
		DecimalFormat amtFormat = new DecimalFormat("##0.00");
		data.put("bareSum", amtFormat.format(totalSum));
		// 餐盒费
		boxBaleFare = productsNum * boxBalePerFare;
		
		// 总费用  = 商品总价   + 餐盒费  + 运费 
		totalSum += boxBaleFare + deliveryFixedFare;
		
		data.put("products", list);
		data.put("sum", amtFormat.format(totalSum));
		data.put("boxBaleFare", boxBaleFare);
		data.put("productsNum", productsNum);
		data.put("orderDetail", orderDetail);
		data.put("orderDate", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
		data.put("mid", mid);
		
		return new  ModelAndView("waimai/saveorder", data);
	}
	
	@RequestMapping(value = "/select")
	public ModelAndView myaddress(
			@RequestParam(value = "cardId") String cardId,			
			@RequestParam(value = "mid") String mid,
			@RequestParam(value = "sum", required = true) String sum,
			HttpServletRequest httpRequest) {
		
		Map<String, Object> data = new HashMap<String, Object>();		
		// 需要验证会员卡是否存在
		if (StringUtils.isEmpty(cardId)) {
			data.put("err_message", "会员卡编号不存在");
			return new ModelAndView("error", data);
		}
		AddressGainInput addressGainInput = new AddressGainInput();
		addressGainInput.setMid(mid);
		addressGainInput.setCardId(cardId);
		AddressGainOutput addressGainOutput = (AddressGainOutput) wizarposOpenRestClient.post(addressGainInput, "/address/gain", AddressGainOutput.class);		
		List<Address> list = addressGainOutput.getResult();		
		
		data.put("list", list);
		data.put("cardId", cardId);
		data.put("mid", mid);
		data.put("sum", sum);
		return new ModelAndView("address/myaddress", data);
	}
	
	@RequestMapping(value = "/selectAdd")
	public ModelAndView selectAddress(@RequestParam(value = "cardId") String cardId,
			@RequestParam(value = "mid") String mid,
			@RequestParam(value = "sum", required = true) String sum,
			HttpServletRequest httpRequest) {		
		Map<String, Object> data = new HashMap<String, Object>();
		// 需要验证会员卡是否存在
		if (StringUtils.isEmpty(cardId)) {
			data.put("err_message", "会员卡编号不存在");
			return new ModelAndView("error", data);
		}
		AddressGainInput addressGainInput = new AddressGainInput();
		addressGainInput.setMid(mid);
		addressGainInput.setCardId(cardId);
		AddressGainOutput addressGainOutput = (AddressGainOutput) wizarposOpenRestClient.post(addressGainInput, "/address/gain", AddressGainOutput.class);		
		List<Address> list = addressGainOutput.getResult();	
		
		data.put("list", list);
		data.put("cardId", cardId);
		data.put("mid", mid);
		data.put("sum", sum);
		return new ModelAndView("waimai/selectAddress", data);
	}
	
	//新增或修改
	@RequestMapping(value = "/to_add")
	public ModelAndView toAddress(
			@RequestParam(value = "cardId") String cardId,
			@RequestParam(value = "mid") String mid,
			@RequestParam(value = "addressId", required = false) String addressId,
			@RequestParam(value = "sum", required = true) String sum,
			HttpServletRequest httpRequest) {
		Map<String, Object> data = new HashMap<String, Object>();
		String openId = (String) httpRequest.getSession().getAttribute("openId");
		if (StringUtils.isEmpty(openId)) {//session过期，跳转到登录注册页面
			return new ModelAndView("forward:/vip/login");
		}
		// 需要验证会员卡是否存在
		if (StringUtils.isEmpty(cardId)) {
			data.put("err_message", "会员卡编号不存在");
			return new ModelAndView("error", data);
		}
		WxAddress address = null;
		if (!StringUtils.isEmpty(addressId)) {
			AddressDetailInput in = new AddressDetailInput();
			in.setMid(mid);
			in.setId(addressId);
			AddressDetailOutput out = (AddressDetailOutput) wizarposOpenRestClient.post(in, "/address/detail", AddressDetailOutput.class);								
			if (out == null) {
				logger.error("请求开放平台查询地址详细接口失败");
				logger.error("mid："+mid);
				logger.error("addressId："+addressId);
				data.put("err_message", "系统错误");
				return new ModelAndView("error", data);
			} else if (SysConstants.OPEN_SUCCESS.equals(out.getCode())) {
				address = (WxAddress) out.getResult();
			} else {
				logger.error("code：" + out.getCode());
				logger.error("message："+ out.getMessage());	
				data.put("err_message", out.getMessage());
				return new ModelAndView("error", data);
			}	
		}
	
		if (address != null && !"".equals(address)) {
			data.put("id", addressId);
			data.put("wx", address);
			String addr = address.getAddress();
			String[] addressArr = (addr != null) ? addr.split(" ") : new String[0];
			data.put("province", addressArr.length > 0 ? addressArr[0] : "");
			data.put("city", addressArr.length > 1 ? addressArr[1] : "");
			data.put("county", addressArr.length > 2 ? addressArr[2] : "");
			StringBuffer sb = new StringBuffer();
			for (int i=3; i < addressArr.length; i++) {
				sb.append(addressArr[i]);
				sb.append(" ");
			}
			data.put("address", sb.toString());
		}
		data.put("cardId", cardId);
		data.put("openId", openId);
		data.put("mid", mid);
		data.put("sum", sum);

		Utils.setSessionToken(httpRequest);

		return new ModelAndView("waimai/addaddress", data);
	}

	@RequestMapping(value = "/add")
	@ResponseBody
	public RespMessage addAddress(
			@RequestParam(value = "cardId", required = false) String cardId,
			@RequestParam(value = "mid") String mid,
			@RequestParam(value = "userName", required = false) String userName,
			@RequestParam(value = "mPhone", required = false) String mPhone,
			@RequestParam(value = "defaultState", required = false) String defaultState,
			@RequestParam(value = "address" , required = false) String address,
			@RequestParam(value = "mZip", required = false) String mZip,
			@RequestParam(value = "id", required = false) String id,
			HttpServletRequest httpRequest) {
		RespMessage res = new RespMessage();

		AddressEditInput addressEditInput = new AddressEditInput();
		addressEditInput.setId(id);
		addressEditInput.setMid(mid);
		addressEditInput.setCardId(cardId);
		addressEditInput.setAddress(address);
		if ("1".equals(defaultState)) {
			addressEditInput.setDefaultState("1");
		} else {
			addressEditInput.setDefaultState("0");
		}		
		addressEditInput.setPhone(mPhone);
		addressEditInput.setUserName(userName);
		addressEditInput.setZipCode(mZip);
		if (id == null || id.isEmpty()) {//新增地址
			addressEditInput.setOperateType("I");			
		} else {//修改原有地址
			addressEditInput.setOperateType("U");
		}
		AddressEditOutput addressEditOutput = (AddressEditOutput) wizarposOpenRestClient.post(addressEditInput, "/address/edit", AddressEditOutput.class);		
		
		if (addressEditOutput == null) {
			logger.error("请求开放平台编辑地址接口失败");
			logger.error("mid："+mid);
			res.setCode(1);
			res.setMessage("编辑地址失败");
		} else if (SysConstants.OPEN_SUCCESS.equals(addressEditOutput.getCode())) {
			res.setCode(0);
		} else {
			logger.error("code：" + addressEditOutput.getCode());
			logger.error("message："+ addressEditOutput.getMessage());	
			res.setCode(1);
			res.setMessage("编辑地址失败");
		}
		
		return res;		
	}

	/**
	 * 外卖订单提交
	 * 
	 * @param token
	 * @param mid
	 * @param sum
	 * @param customer
	 * @param address
	 * @param tel
	 * @param orderDetail
	 * @param remark
	 * @param nonceStr
	 * @param ticketInfoIds
	 * @param payType
	 * @param httpRequest
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	@RequestMapping(value = "/order_submit", method = RequestMethod.POST)
	public @ResponseBody RespMessage orderSubmit(
			@RequestParam(value = "token", required = true) String token,
			@RequestParam(value = "mid", required = true) String mid,
			@RequestParam(value = "sum", required = true) String sum,
			@RequestParam(value = "customer", required = true) String customer,
			@RequestParam(value = "address", required = true) String address,
			@RequestParam(value = "tel", required = true) String tel,
			@RequestParam(value = "orderDetail", required = true) String orderDetail,
			@RequestParam(value = "remark", required = true) String remark,
			@RequestParam(value = "nonceStr", required = true) String nonceStr,
			@RequestParam(value = "ticketInfoIds", required = true) String ticketInfoIds,
			@RequestParam(value = "payType", required = true) String payType,
			@RequestParam(value = "deliveryTime", required = true) String deliveryTime,
			@RequestParam(value = "shopMid", required = false) String shopMid,
			HttpServletRequest httpRequest) throws UnsupportedEncodingException {
		RespMessage res = new RespMessage();
		String cardId = (String) httpRequest.getSession().getAttribute("mrtCardId");
		String cardNo = (String) httpRequest.getSession().getAttribute("mrtCardNo");
		if (StringUtils.isEmpty(cardId) || StringUtils.isEmpty(cardNo)) {//session过期，跳转到登录注册页面
			res.setCode(2);
			return res;	
		}
		
		if(Utils.isRepeatSubmit(httpRequest, token)) {
			res.setCode(1);
			res.setMessage("订单重复提交");
			return res;
		}
		CanyinSalesOrderSubmitInput salesOrderSubmitInput = new CanyinSalesOrderSubmitInput();
		salesOrderSubmitInput.setMid(mid);
		salesOrderSubmitInput.setShopMid(shopMid);
		salesOrderSubmitInput.setTakeoutCustomer(customer);
		salesOrderSubmitInput.setTakeoutAddr(address);
		salesOrderSubmitInput.setTakeoutTel(tel);
		salesOrderSubmitInput.setOrderType("4"); //餐饮类型线上外卖
		salesOrderSubmitInput.setOrderSource("2"); //微信订单
		salesOrderSubmitInput.setStatus("3");// 3外卖下单
		salesOrderSubmitInput.setAmount(sum);
		JSONArray details = JSON.parseArray(orderDetail);
		List<CateringDetail> orderDetails = new ArrayList<CateringDetail>();
		for (int i = 0; i < details.size(); i++) {
			JSONObject od = details.getJSONObject(i);
			CateringDetail cateringDetail = new CateringDetail();
			cateringDetail.setProductId(od.getString("id"));
			cateringDetail.setPrice(od.getString("price"));
			cateringDetail.setQty(od.getString("qty"));
			float amt = od.getFloat("price") * od.getInteger("qty");
			cateringDetail.setAmount(String.valueOf(amt));
			cateringDetail.setRemark(od.getString("productRemark"));
			orderDetails.add(cateringDetail);
		}
		salesOrderSubmitInput.setOrderDetail(orderDetails);
		salesOrderSubmitInput.setPrint(true);
		salesOrderSubmitInput.setRemark(remark);
		salesOrderSubmitInput.setCardId(cardId);
		salesOrderSubmitInput.setDeliveryTime(deliveryTime);
		StringBuffer url = null;
		// 请求开放平台获取appId
		MerchantDefQueryInput merchantDefQueryInput = new MerchantDefQueryInput();
		merchantDefQueryInput.setMid(mid);
		MerchantDefQueryOutput merchantDefOuptut = (MerchantDefQueryOutput) wizarposOpenRestClient.post(merchantDefQueryInput, "/merchantdef/info", MerchantDefQueryOutput.class);
		if (merchantDefOuptut != null && "0".equals(merchantDefOuptut.getCode())) {
			MerchantDef merchant = merchantDefOuptut.getResult();
			url = new StringBuffer("https://open.weixin.qq.com/connect/oauth2/authorize?appid=");
			url.append(merchant.getWeixinAppId());
			url.append("&redirect_uri=http%3a%2f%2f");
			url.append(messageSource.getMessage(SysConstants.SERVICE_DNS, null,
					Locale.ENGLISH));
			String path = httpRequest.getContextPath();
			path = path.replace("/", "");
			url.append("%2f" + path +"%2foauth%2fcatering_menuinfo&response_type=code&scope=snsapi_base&state=");
			url.append(mid);
			url.append("ORDERID");
			salesOrderSubmitInput.setUrl(url.toString());
		}
		CanyinSalesOrderSubmitOutput salesOrderSubmitOutput = (CanyinSalesOrderSubmitOutput) wizarposOpenRestClient.post(salesOrderSubmitInput, "/dzx/saleorder/submit", CanyinSalesOrderSubmitOutput.class); 
		if (salesOrderSubmitOutput == null) {
			logger.error("呼叫开放平台餐饮订单提交出错，外卖点餐失败。");
			res.setCode(1);
			res.setMessage("系统异常");
			return res;			
		} else if (SysConstants.OPEN_SUCCESS.equals(salesOrderSubmitOutput.getCode()) || "60032".equals(salesOrderSubmitOutput.getCode())) {
			CanyinSalesOrderSubmitOutput.Result result = salesOrderSubmitOutput.getResult();
			String orderId = result.getOrderId();
			// 推送管家号下单模板消息
			wPosHttpClient.pushHouseKeeperOrderSubmitMsg(mid, orderId);
			// 记录绑定信息
			CateringSaleOrderBindingInput saleOrderBindingInput = new CateringSaleOrderBindingInput();
			saleOrderBindingInput.setMid(mid);
			saleOrderBindingInput.setCardId(cardId);
			saleOrderBindingInput.setSaleOrderId(orderId);
			CateringSaleOrderBindingOutput saleOrderBindingOutput = (CateringSaleOrderBindingOutput) wizarposOpenRestClient.post(saleOrderBindingInput, "/catering/saleorder/binding", CateringSaleOrderBindingOutput.class);			
			if (saleOrderBindingOutput == null) {
				logger.error("呼叫开放平台记录绑定信息接口出错，外卖点餐失败。");
				res.setCode(1);
				res.setMessage("系统异常");
				return res;					
			} else if (SysConstants.OPEN_SUCCESS.equals(saleOrderBindingOutput.getCode())) {
				Utils.removeSessionToken(httpRequest);
				if ("1".equals(payType)) { // 会员卡支付
					CateringSaleOrderMemberCardPayInput memberCardPayInput = new CateringSaleOrderMemberCardPayInput();					
					memberCardPayInput.setMid(mid);
					memberCardPayInput.setOrderId(orderId);
					memberCardPayInput.setAmount(sum);
					if (!StringUtils.isEmpty(ticketInfoIds)) {
						memberCardPayInput.setTicketInfoIds(Arrays.asList(ticketInfoIds.split(",")));
					}
					memberCardPayInput.setCardNo(cardNo);
					memberCardPayInput.setPrint(true);
					if (url != null) {
						memberCardPayInput.setUrl(url.toString());
					}
					CateringSaleOrderMemberCardPayOutput memberCardPayOutput =  (CateringSaleOrderMemberCardPayOutput) wizarposOpenRestClient.post(memberCardPayInput, "/catering/memberCardPay", CateringSaleOrderMemberCardPayOutput.class);
					if (memberCardPayOutput == null) {
						logger.error("餐饮订单会员卡支付失败，单号：" + orderId);
						res.setCode(1);
						res.setMessage("系统异常");
						return res;				
					} else if (SysConstants.OPEN_SUCCESS.equals(memberCardPayOutput.getCode())) {
						CateringSaleOrderMemberCardPayOutput.Result memberCardPayResult = memberCardPayOutput.getResult();
						if (memberCardPayResult != null) {
							// 推送管家号收款模板消息
							wPosHttpClient.pushHouseKeeperPaymentMsg(mid, memberCardPayResult.getTranLogId());	
						}
						res.setObj(orderId);
						return res;
					} else if ("60010".equals(memberCardPayOutput.getCode())) { // 会员卡余额不足
						res.setCode(-1);
						res.setMessage(memberCardPayOutput.getMessage());
						res.setObj(orderId);
						return res;							
					} else {
						logger.error("code：" + memberCardPayOutput.getCode());
						logger.error("message：" + memberCardPayOutput.getMessage());
						res.setCode(1);
						return res;						
					}
				} else {
					res.setObj(orderId);
					return res;
				}
				
			} else {
				logger.error("code：" + saleOrderBindingOutput.getCode());
				logger.error("message：" + saleOrderBindingOutput.getMessage());
				res.setCode(1);
				return res;					
			}
		} else {
			logger.error("code：" + salesOrderSubmitOutput.getCode());
			logger.error("message：" + salesOrderSubmitOutput.getMessage());
			res.setCode(1);
			return res;				
		}
	}

}
